﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace KruskalAlgorithm
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
            Clear();
            loadCode();
        }

        #region Member Variables
        const int m_nRadius = 24;
        const int m_nHalfRadius = (m_nRadius / 2);
        const string codeKruskal = "MST-KRUSKAL(G, w)\nA = {}\nfor each vertex v € G.V\n    MAKE-SET(v)\n    sort the edges of G.E into nondecreasing order by weight w\nfor each edge (u,v) € G.E, taken in nondecreasing order by weight\n    if FIND-SET(u) != FIND-SET(v)\n        A = A U {(u,v)}\n        UNION(u,v)\nreturn A";
        const string codePrim = "MST-PRIM(G, w, r)\nfor each u € G.V\n    u.key = infinity\n    u.p = NIL\nr.key = 0\nQ = G.V\nwhile Q != {}\n    u = EXTRACT-MIN(Q)\n    for each v € G.Adj[u]\n        if v € Q and w(u,v) < v.key\n            v.p = u\n            v.key = w(u,v)\nreturn\n";
    
        Color m_colVertex = Color.Aqua;
        Color m_colVertex_current = Color.Green;
        Color m_colEdge_outSolution = Color.Black;
        Color m_colEdge_inSolution = Color.Red;

        List<Edge> m_lstEdgesInitial, m_lstEdgesFinal;
        List<Vertex> m_lstVertices;

        Vertex m_vFirstVertex, m_vSecondVertex;

        bool m_bDrawEdge, m_bSolved;

        int selectedAlgorithm = 1; //1 = KRUSKAL, 2 = PRIM
        int stepNumber = 1;
        int totalSteps = 0;

        int indexCurrentEdKruskal = 0;
        Edge currentEdKruskal = null;
        Vertex currentVRoot1Kruskal, currentVRoot2Kruskal = null;
        List<Edge> LEdgesRetunKruskal = new List<Edge>();
        Stack<StackItemKruskal> stackKruskal = new Stack<StackItemKruskal>();
        const int stepNumberFinalKruskal = 9;

        Vertex startingVertexPrim = null;
        List<Vertex> remainingVerticesPrim = null;
        Vertex currentMinPrim = null;
        Vertex currentAdjPrim = null;
        int currentAdjCostPrim = 0;
        Edge currentEdgePrim = null;
        List<Edge> currentEdgesPrim = null;
        List<Edge> LEdgesRetunPrim = new List<Edge>();
        Stack<StackItemPrim> stackPrim = new Stack<StackItemPrim>();
        const int stepNumberFinalPrim = 12;
        double minEdge;

        #endregion

        #region Events
        private void panel1_MouseClick(object sender, MouseEventArgs e)
        {
            Point pClicked = new Point(e.X - m_nHalfRadius, e.Y - m_nHalfRadius);
            switch (Control.ModifierKeys)
            {
                case Keys.Control:
                    if (!m_bDrawEdge)
                    {
                        m_vFirstVertex = GetSelectedVertex(pClicked);
                        m_bDrawEdge = true;
                    }
                    else
                    {
                        m_vSecondVertex = GetSelectedVertex(pClicked);
                        m_bDrawEdge = false;
                        if (m_vFirstVertex != null && m_vSecondVertex != null && m_vFirstVertex.Name != m_vSecondVertex.Name)
                        {
                            frmCost formCost = new frmCost();
                            formCost.ShowDialog();

                            Point pStringPoint = GetStringPoint(m_vFirstVertex.pPosition, m_vSecondVertex.pPosition);
                            m_lstEdgesInitial.Add(new Edge(m_vFirstVertex, m_vSecondVertex, formCost.m_nCost, pStringPoint));
                            LEdgesRetunKruskal.Add(new Edge(m_vFirstVertex, m_vSecondVertex, formCost.m_nCost, pStringPoint));
                            LEdgesRetunPrim.Add(new Edge(m_vFirstVertex, m_vSecondVertex, formCost.m_nCost, pStringPoint));
                        }
                    }
                    break;
                case Keys.Alt:
                    if (selectedAlgorithm != 2)
                    {
                        return;
                    }
                    Vertex startingVertex = GetSelectedVertex(pClicked);
                    //startingVertex.vColor = Color.Blue;
                    startingVertexPrim = startingVertex;
                    break;
                default:
                    m_lstVertices.Add(new Vertex(m_lstVertices.Count, pClicked, 0, 0));
                    break;

            }

            panel1.Invalidate();
            /*  old code
            if (Control.ModifierKeys == Keys.Control)//if Ctrl is pressed
            {
                if (!m_bDrawEdge)
                {
                    m_vFirstVertex = GetSelectedVertex(pClicked);
                    m_bDrawEdge = true;
                }
                else
                {
                    m_vSecondVertex = GetSelectedVertex(pClicked);
                    m_bDrawEdge = false;
                    if (m_vFirstVertex != null && m_vSecondVertex != null && m_vFirstVertex.Name != m_vSecondVertex.Name)
                    {
                        frmCost formCost = new frmCost();
                        formCost.ShowDialog();

                        Point pStringPoint = GetStringPoint(m_vFirstVertex.pPosition, m_vSecondVertex.pPosition);
                        LEdgesRetunKruskal.Add(new Edge(m_vFirstVertex, m_vSecondVertex, formCost.m_nCost, pStringPoint));
                        panel1.Invalidate();
                    }
                }
            }
            else
            {
                m_lstVertices.Add(new Vertex(m_lstVertices.Count, pClicked, 0, 0));
                panel1.Invalidate();
            }*/
        }

        private void panel1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            DrawVertices(g);
            DrawEdges(g);
            g.Dispose();
        }

        private void btnSolve_Click(object sender, EventArgs e)
        {
            if (m_lstVertices.Count > 2)
            {
                if (m_lstEdgesInitial.Count < m_lstVertices.Count - 1)
                {
                    MessageBox.Show("Missing Edges", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                else
                {
                    /* this is the enter of the solution 
                     * we can change this part so that it can fit for two algorithm
                     */
                    btnSolve.Enabled = false;
                    int nTotalCost = 0;
                    SolveGraph(ref nTotalCost);
                    m_bSolved = true;
                    panel1.Invalidate();
                    MessageBox.Show("Number of Steps:" +totalSteps.ToString(), "Solution", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("Clear form ?", "Alert", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
            
            if (dr == DialogResult.Yes)
            {
                stepNumber = 1;
                currentVRoot1Kruskal = null;
                currentVRoot2Kruskal = null;
                currentMinPrim = null;
                currentAdjPrim = null;
                btnSolve.Enabled = true;
                Graphics g = panel1.CreateGraphics();
                g.Clear(panel1.BackColor);
                Clear();
            }
            TextBoxShow();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (selectedAlgorithm == 2 && startingVertexPrim == null)
            {
                MessageBox.Show("Please Select Start Point First");
                return;
            }
            this.forwardStep();
            this.TextBoxShow();
        }


        private void PreviousStep_Click(object sender, EventArgs e)
        {
            this.backwardStep();
            this.TextBoxShow();
        }

        private void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            //radioButton2.Checked = false;
            selectedAlgorithm = 1;
            loadCode();
        }

        private void radioButton2_CheckedChanged(object sender, EventArgs e)
        {
            //radioButton1.Checked = false;
            selectedAlgorithm = 2;
            loadCode();
        }

        #endregion

        #region Methods

        #region Drawing

        private void DrawEdges(Graphics g)
        {
            List<Edge> edges = selectedAlgorithm == 1 ? LEdgesRetunKruskal : LEdgesRetunPrim;
            foreach (Edge e in edges)
            {
                Pen P = new Pen(e.IsInSolution ? m_colEdge_inSolution : m_colEdge_outSolution);
                Point pV1 = new Point(e.V1.pPosition.X + m_nHalfRadius, e.V1.pPosition.Y + m_nHalfRadius);
                Point pV2 = new Point(e.V2.pPosition.X + m_nHalfRadius, e.V2.pPosition.Y + m_nHalfRadius);
                g.DrawLine(P, pV1, pV2);
                DrawString(e.Cost.ToString(), e.StringPosition, g);
            }
            
            
        }

        private void DrawString(string strText, Point pDrawPoint, Graphics g)
        {
            Font drawFont = new Font("Arial", 15);
            SolidBrush drawBrush = new SolidBrush(Color.Black);
            Point sPoint;
            if (strText.Length == 1)
            {
                sPoint = new Point(pDrawPoint.X + 4, pDrawPoint.Y + 1);
            }
            else
            {
                sPoint = new Point(pDrawPoint.X - 2, pDrawPoint.Y + 1);
            }
            g.DrawString(strText, drawFont, drawBrush, sPoint);
        }

        private void DrawVertices(Graphics g)
        {
            foreach (Vertex v in m_lstVertices)
            {
                //Pen P = new Pen(((v == currentVRoot1Kruskal) || (v == currentVRoot2Kruskal) || (v == currentMinPrim) || (v == currentAdjPrim)) ? m_colVertex_current : m_colVertex);
                Pen P = new Pen(((currentVRoot1Kruskal != null && v.Name == currentVRoot1Kruskal.Name) ||
                    (currentVRoot2Kruskal != null && v.Name == currentVRoot2Kruskal.Name) ||
                    (currentMinPrim != null && v.Name == currentMinPrim.Name) ||
                    (currentAdjPrim != null && v.Name == currentAdjPrim.Name)) ? m_colVertex_current : m_colVertex);
                Brush B = new SolidBrush((startingVertexPrim != null && v.Name == startingVertexPrim.Name) ? Color.Blue : P.Color);
                g.DrawEllipse(P, v.pPosition.X, v.pPosition.Y, m_nRadius, m_nRadius);
                g.FillEllipse(B, v.pPosition.X, v.pPosition.Y, m_nRadius, m_nRadius);
                DrawString(v.Name.ToString(), v.pPosition, g);
            }
             
        }

        private Vertex GetSelectedVertex(Point pClicked)
        {
            Vertex vReturn = null;
            double dDistance;
            foreach (Vertex v in m_lstVertices)
            {
                dDistance = GetDistance(v.pPosition, pClicked);
                if (dDistance <= m_nRadius)
                {
                    vReturn = v;
                    break;
                }
            }
            return vReturn;
        }

        private double GetDistance(Point pStart, Point pFinish)
        {
            return Math.Sqrt(Math.Pow(pStart.X - pFinish.X, 2) + Math.Pow(pStart.Y - pFinish.Y, 2));
        }

        private Point GetStringPoint(Point pStart, Point pFinish)
        {
            int X = (pStart.X + pFinish.X) / 2;
            int Y = (pStart.Y + pFinish.Y) / 2;
            return new Point(X, Y);
        }
        #endregion

        private void loadFile(String fileName) {
            if (fileName.Length == 0)
            {
                fileName = "testFile.v10.c10.txt";
            }

            string[] lines = System.IO.File.ReadAllLines(@fileName);

            int vertexMaxNumber = 0;
            char[] spt = { '#', '-' };
            foreach (string line in lines) {
                // line = "#Vertex1-#Vertex2-Cost"
                string[] values = line.Split(spt, StringSplitOptions.RemoveEmptyEntries);
                int numVertex1 = Convert.ToInt32(values[0]);
                int numVertex2 = Convert.ToInt32(values[1]);
                if (numVertex1 > vertexMaxNumber)
                {
                    vertexMaxNumber = numVertex1;
                }
                if (numVertex2 > vertexMaxNumber) {
                    vertexMaxNumber = numVertex2;
                }
            }

            for (int i=0; i<lines.Length; i++) {
                string line = lines[i];
                // line = "#Vertex1-#Vertex2-Cost"
                string[] values = line.Split(spt, StringSplitOptions.RemoveEmptyEntries);
                int numVertex1 = Convert.ToInt32(values[0]);
                int numVertex2 = Convert.ToInt32(values[1]);
                int cost = Convert.ToInt32(values[2]);

                // Create Vertex1 if it doesn't exist
                Vertex vertex1 = null;
                foreach(Vertex v in m_lstVertices) {
                    if (v.Name == numVertex1) {
                        vertex1 = v;
                    }
                }
                if (vertex1 == null) {
                    vertex1 = new Vertex(numVertex1, getPosition(numVertex1, vertexMaxNumber), 0, 0);
                    m_lstVertices.Add(vertex1);
                }

                // Create Vertex2 if it doesn't exist
                Vertex vertex2 = null;
                foreach(Vertex v in m_lstVertices) {
                    if (v.Name == numVertex2) {
                        vertex2 = v;
                    }
                }
                if (vertex2 == null) {
                    vertex2 = new Vertex(numVertex2, getPosition(numVertex2, vertexMaxNumber), 0, 0);
                    m_lstVertices.Add(vertex2);
                }

                // Create the Edge between Vertex1 and Vertex2
                LEdgesRetunKruskal.Add(new Edge(vertex1, vertex2, cost, GetStringPoint(vertex1.pPosition, vertex2.pPosition)));
                LEdgesRetunPrim.Add(new Edge(vertex1, vertex2, cost, GetStringPoint(vertex1.pPosition, vertex2.pPosition)));
                m_lstEdgesInitial.Add(new Edge(vertex1, vertex2, cost, GetStringPoint(vertex1.pPosition, vertex2.pPosition)));
            }

            panel1.Invalidate();
        }

        private System.Drawing.Point getPosition(int vertexNumber, int vertexMaxNumber) {
            // Imagine a circle, the point will be on the circle at the angle: 2 * pi * vertexNumber / (vertexMaxNumber + 1)
            // for example, if vertexNumber = 0, the point will be at the angle 0
            // if vertexNumber = 5 and vertexMaxNumber = 9, the point will be at the angle pi

            double angle = 2 * System.Math.PI * vertexNumber / (vertexMaxNumber + 1);
            int r = 160;
            int middleX = 201, middleY = 215;
            double x = middleX + r * System.Math.Cos(angle);
            double y = middleY - r * System.Math.Sin(angle);

            Point P = new Point(Convert.ToInt32(x), Convert.ToInt32(y));

            return P;
            /*
            int angle = 2 * Math.PI * vertexNumber / (vertexMaxNumber + 1);
            System.Drawing.Point center = new System.Drawing.Point(402/2, 429/2);
            int radius = 100;
            return new System.Drawing.Point(center.X + radius * Math.cos(angle), center.Y + radius * Math.sin(angle));
            */
        }

        private void Clear()
        {

            m_lstVertices = new List<Vertex>();
            m_lstEdgesInitial = new List<Edge>();
            m_bSolved = false;
            m_vFirstVertex = m_vSecondVertex = null;
        }

		/*
		MST-KRUSKAL(G, w)
		1 A = {}
		2 for each vertex v € G.V
		3     MAKE-SET(v)
		4 sort the edges of G.E into nondecreasing order by weight w
		5 for each edge (u,v) € G.E, taken in nondecreasing order by weight
		6     if FIND-SET(u) != FIND-SET(v)
		7         A = A U {(u,v)}
		8         UNION(u,v)
		9 return A
		*/

        /*
        MST-PRIM(G, w, r)
        1 for each u € G.V
		2     u.key = infinity
		3     u.p = NIL
		4 r.key = 0
		5 Q = G.V
		6 while Q != {}
		7     u = EXTRACT-MIN(Q)
		8     for each v € G.Adj[u]
		9         if v € Q and w(u,v) < v.key
		10            v.p = u
		11            v.key = w(u,v)
         */

        private void SolveGraph(ref int nTotalCost)
        {
            while (stepNumber != (2 - selectedAlgorithm) * stepNumberFinalKruskal + (selectedAlgorithm - 1) * stepNumberFinalPrim) {
                forwardStep();
            }
            /*
            //this is the enter of the Kruskal Algorithm
            List<Edge> lstEdgesRetun = new List<Edge>(m_lstEdgesInitial.Count);            // 1 A = {}
            Edge.QuickSort(m_lstEdgesInitial, 0, m_lstEdgesInitial.Count - 1);             // 4 sort the edges of G.E into nondecreasing order by weight w
            foreach (Edge ed in m_lstEdgesInitial)                                         // 5 for each edge (u,v) € G.E, taken in nondecreasing order by weight
            {
                Vertex vRoot1, vRoot2;
                vRoot1 = ed.V1.GetRoot();
                vRoot2 = ed.V2.GetRoot();
                if (vRoot1.Name != vRoot2.Name)                                            // 6     if FIND-SET(u) != FIND-SET(v)
                {
                    nTotalCost += ed.Cost;
                    lstEdgesRetun.Add(new Edge(ed.V1, ed.V2, ed.Cost, ed.StringPosition)); // 7         A = A U {(u,v)}
                    Vertex.Join(vRoot1, vRoot2);                                           // 8         UNION(u,v)
                }
            }
            return lstEdgesRetun;
            */
        }

        private void forwardStep() {
            switch(selectedAlgorithm) {
                case 1: // Kruskal
                    #region Krukal
                    switch (stepNumber)
                    {
                        case 1: // 1 A = {}
                            //LEdgesRetunKruskal = new List<Edge>(m_lstEdgesInitial.Count);
                            stepNumber = 2;
                            break;
                        case 2: // 2 for each vertex v € G.V
                                // 3     MAKE-SET(v)
                            stepNumber = 4;
                            break;
                        case 4: // 4 r.key = 0
                            List<Edge> temp = new List<Edge>();
                            foreach (Edge e in LEdgesRetunKruskal)
                            {
                                int i = 0;
                                while (i < temp.Count && temp[i].Cost <= e.Cost)
                                {
                                    i++;
                                }
                                temp.Insert(i, e);
                            }
                            LEdgesRetunKruskal = temp;
                            //Edge.QuickSort(LEdgesRetunKruskal, 0, LEdgesRetunKruskal.Count - 1);
                            stepNumber = 5;
                            break;
                        case 5: // 5 for each edge (u,v) € G.E, taken in nondecreasing order by weight
                            if (m_lstEdgesInitial.Count > 0)
                            {
                                currentEdKruskal = LEdgesRetunKruskal[indexCurrentEdKruskal];
                                indexCurrentEdKruskal++;
                                Edge todelete = null;
                                foreach (Edge e in m_lstEdgesInitial)
                                {
                                    if (e.V1.Name == currentEdKruskal.V1.Name && e.V2.Name == currentEdKruskal.V2.Name)
                                    {
                                        todelete = e;
                                    }
                                }
                                m_lstEdgesInitial.Remove(todelete);
                                stepNumber = 6;
                            }
                            else
                            {
                                stepNumber = 9;
                            }
                            break;
                        case 6: // 6     if FIND-SET(u) != FIND-SET(v)
                            currentVRoot1Kruskal = currentEdKruskal.V1.GetRoot();
                            currentVRoot2Kruskal = currentEdKruskal.V2.GetRoot();
                            if (currentVRoot1Kruskal.Name != currentVRoot2Kruskal.Name)
                            {
                                stepNumber = 7;
                            }
                            else
                            {
                                stepNumber = 5;
                            }
                            break;
                        case 7: // 7         A = A U {(u,v)}
                            //LEdgesRetunKruskal.Add(new Edge((Vertex) currentEdKruskal.V1.Clone(), (Vertex) currentEdKruskal.V2.Clone(), currentEdKruskal.Cost, currentEdKruskal.StringPosition));
                            foreach (Edge e in LEdgesRetunKruskal) {
                                if ((e.V1.Name == currentEdKruskal.V1.Name) && (e.V2.Name == currentEdKruskal.V2.Name)) {
                                    e.isInSolution = true;
                                }
                            }
                            stepNumber = 8;
                            break;
                        case 8: // 8         UNION(u,v)
                            Vertex.Join((Vertex) currentVRoot1Kruskal, (Vertex) currentVRoot2Kruskal);
                            stepNumber = 5;
                            break;
                        case 9: // 9 return A
                            // End of the algorithm
                            break;
                        default:
                            break;
                    }
                    stackKruskal.Push(new StackItemKruskal(indexCurrentEdKruskal, currentEdKruskal, currentVRoot1Kruskal, currentVRoot2Kruskal, LEdgesRetunKruskal, stepNumber));
#endregion
                    break;

                case 2: // Prim
                    switch (stepNumber)
                    {
                        case 1: // 1 for each u € G.V
						        // 2     u.key = infinity
						        // 3     u.p = NIL
						    foreach (Vertex u in  m_lstVertices ) {
						        u.Key = double.PositiveInfinity;
						        u.P = -1;
						    }
                            stepNumber = 4;
                            break;
                        case 4: // 4 r.key = 0
                            startingVertexPrim.Key = 0;
                            stepNumber = 5;
                            break;
                        case 5: // 5 Q = G.V
                            remainingVerticesPrim = new List<Vertex>();
                            foreach (Vertex u in  m_lstVertices ) {
                                remainingVerticesPrim.Add((Vertex)u.Clone());
                            }
                            stepNumber = 6;
                            break;
                        case 6: // 6 while Q != {}
                            if (remainingVerticesPrim.Count > 0) {
                                stepNumber = 7;
                            } else {
                                stepNumber = 12;
                            }
                            break;
                        case 7: // 7     u = EXTRACT-MIN(Q)
                            Edge temp = null;
                            minEdge = double.PositiveInfinity;
                            foreach (Edge e in m_lstEdgesInitial) {
                                foreach (Vertex v in remainingVerticesPrim)
                                {
                                    if (e.Cost < minEdge && ((v.Name == e.V1.Name) || (v.Name == e.V2.Name)))
                                    {
                                        currentMinPrim = v;
                                        minEdge = e.Cost;
                                        temp = e;
                                    }
                                }
                            }
                            remainingVerticesPrim.Remove(currentMinPrim);
                            foreach (Edge e in LEdgesRetunPrim)
                            {
                                if (e.V1.Name == temp.V1.Name && e.V2.Name == temp.V2.Name)
                                {
                                    e.isInSolution = true;
                                }
                            }

                            currentEdgesPrim = new List<Edge>();
                            foreach (Edge e in m_lstEdgesInitial) {
                                if (e.V1.Name == currentMinPrim.Name || e.V2.Name == currentMinPrim.Name)
                                {
                                    currentEdgesPrim.Add(e);
                                }
                            }
                            stepNumber = 8;
                            break;
                        case 8: // 8     for each v € G.Adj[u]
                            if (currentEdgesPrim.Count > 0) {
                                currentEdgePrim = currentEdgesPrim[0];
                                currentAdjPrim = currentEdgesPrim[0].V1.Name == currentMinPrim.Name ? currentEdgesPrim[0].V2 : currentEdgesPrim[0].V1;
                                currentAdjCostPrim = currentEdgesPrim[0].Cost;
                                currentEdgesPrim.Remove(currentEdgesPrim[0]);
                                stepNumber = 9;
                            } else {
                                stepNumber = 6;
                            }
                            break;
                        case 9: // 9         if v € Q and w(u,v) < v.key
                            stepNumber = 8;
                            foreach (Vertex v in remainingVerticesPrim)
                            {
                                if (v.Name == currentAdjPrim.Name && currentAdjCostPrim < currentAdjPrim.Key)
                                {
                                    stepNumber = 10;
                                }
                            }
                            break;
                        case 10: // 10            v.p = u
                            int oldp = currentAdjPrim.P;
                            currentAdjPrim.P = currentMinPrim.Name;
                            foreach (Edge e in LEdgesRetunPrim)
                            {
                                if (e.V1.Name == currentEdgePrim.V1.Name && e.V2.Name == currentEdgePrim.V2.Name)
                                {
                                    e.isInSolution = true;
                                }
                                if (oldp != -1 && oldp != startingVertexPrim.Name && ((e.V1.Name == oldp && e.V2.Name == currentEdgePrim.V2.Name) || (e.V2.Name == oldp && e.V1.Name == currentEdgePrim.V1.Name)))
                                {
                                    e.isInSolution = false;
                                }
                            }
                            stepNumber = 11;
                            break;
                        case 11: // 11            v.key = w(u,v)
                            currentAdjPrim.Key = currentAdjCostPrim;
                            stepNumber = 8;
                            break;
                        case 12:
                            // End of the algorithm
                            break;
                        default:
                            break;
                    }
                    stackPrim.Push(new StackItemPrim(remainingVerticesPrim, currentMinPrim, currentAdjPrim, currentAdjCostPrim, currentEdgesPrim, LEdgesRetunPrim, currentEdgePrim, stepNumber));
                    break;
                default:
                    break;
            }
            totalSteps++;
            panel1.Invalidate();
        }

        private void backwardStep()
        {
            switch (selectedAlgorithm)
            {
                case 1: // Kruskal
                    StackItemKruskal sik = stackKruskal.Pop();
                    indexCurrentEdKruskal = sik.indexCurrentEdKruskal;
                    currentEdKruskal = sik.currentEd;
                    currentVRoot1Kruskal = sik.currentVRoot1;
                    currentVRoot2Kruskal = sik.currentVRoot2;
                    LEdgesRetunKruskal = sik.LEdgesRetun;
                    stepNumber = sik.stepNumber;
                    break;
                case 2: // Prim
                    StackItemPrim sip = stackPrim.Pop();
					remainingVerticesPrim = sip.getRemainingVertices;
                    currentMinPrim = sip.getCurrentMin;
					currentAdjPrim = sip.getCurrentAdj;
					currentAdjCostPrim = sip.getCurrentAdjCost;//CurrentAdjCost;
					currentEdgesPrim = sip.getCurrentEdges;//.CurrentEdges;
                    currentEdgePrim = sip.getCurrentEdgePrim;
                    stepNumber = sip.stepNumber;
                    break;
                default:
                    break;
            }
            totalSteps--;
            panel1.Invalidate();
        }

        #region TextBox

        private void loadCode()
        {
            if (selectedAlgorithm == 1)
            {
                this.richTextBox1.Text = codeKruskal;
            }
            else
            {
                this.richTextBox1.Text = codePrim;
            }
        }

        private void resetHighLight()
        {
            richTextBox1.SelectAll();
            richTextBox1.SelectionBackColor = Color.White;
        }

        private void highLightText(int _startIndex, int _endIndex)
        {
            int startIndex = _startIndex;
            int endIndex = _endIndex;
            resetHighLight();
            if (startIndex < 0 || endIndex > richTextBox1.Lines.Length)
            {
                return;
            }
            for (int lineIndex = startIndex; lineIndex <= endIndex; lineIndex++)
            {
                richTextBox1.Select(richTextBox1.GetFirstCharIndexFromLine(lineIndex), richTextBox1.Lines[lineIndex].Length);
                richTextBox1.SelectionBackColor = Color.Lime;
            }
        }

        public void TextBoxShow()
        {
            int start=0, end=0;
            resetHighLight();
            if (selectedAlgorithm == 1)
            {
                #region Kru
                switch (stepNumber)
                {
                    case 1: // 1 A = {}
                        start = 1;
                        end = 1;
                        break;
                    case 2: // 2 for each vertex v € G.V
                        // 3     MAKE-SET(v)
                        start = 2;
                        end = 3;
                        break;
                    case 4: // 4 r.key = 0
                        start = 4;
                        end = 4;
                        break;
                    case 5: // 5 for each edge (u,v) € G.E, taken in nondecreasing order by weight
                        start = 5;
                        end = 5;
                        break;
                    case 6: // 6     if FIND-SET(u) != FIND-SET(v)
                        start = 6;
                        end = 6;
                        break;
                    case 7: // 7         A = A U {(u,v)}
                        start = 7;
                        end = 7;
                        break;
                    case 8: // 8         UNION(u,v)
                        start = 8;
                        end = 8;
                        break;
                    case 9: // 9 return A
                        // End of the algorithm
                        start = 9;
                        end = 9;
                        break;
                    default:
                        break;
                }
                #endregion
            }
            else
            {
                #region Prim
                switch (stepNumber)
                {
                    case 1: // 1 for each u € G.V
                        // 2     u.key = infinity
                        // 3     u.p = NIL
                        start = 1;
                        end = 3;
                        break;
                    case 4: // 4 r.key = 0
                        start = 4;
                        end = 4;
                        break;
                    case 5: // 5 Q = G.V
                        start = 5;
                        end = 5;
                        break;
                    case 6: // 6 while Q != {}
                        start = 6;
                        end = 6;
                        break;
                    case 7: // 7     u = EXTRACT-MIN(Q)
                        start = 7;
                        end = 7;
                        break;
                    case 8: // 8     for each v € G.Adj[u]
                        start = 8;
                        end = 8;
                        break;
                    case 9: // 9         if v € Q and w(u,v) < v.key
                        start = 9;
                        end = 9;
                        break;
                    case 10: // 10            v.p = u
                        start = 10;
                        end = 10;
                        break;
                    case 11: // 11            v.key = w(u,v)
                        // TODO
                        start = 11;
                        end = 11;
                        break;
                    case 12:
                        // End of the algorithm
                        start = 12;
                        end = 12;
                        break;
                    default:
                        break;
                }
                #endregion
            }
            highLightText(start, end);
        }
        #endregion

        private void button1_Click_1(object sender, EventArgs e)
        {
            if (openFileDialog1 == null)
            {
                openFileDialog1 = new OpenFileDialog();
            }

            openFileDialog1.InitialDirectory = System.Environment.CurrentDirectory;
           
            openFileDialog1.ShowDialog();

            
        }

        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            stepNumber = 1;
            currentVRoot1Kruskal = null;
            currentVRoot2Kruskal = null;
            currentMinPrim = null;
            currentAdjPrim = null;
            btnSolve.Enabled = true;
            Graphics g = panel1.CreateGraphics();
            g.Clear(panel1.BackColor);
            Clear();
            loadFile(openFileDialog1.FileName);
            TextBoxShow();
        }


        #endregion

        

       


    }
}
